package cn.remex.core;

import cn.remex.core.util.PackageUtil;
import cn.remex.core.util.StringHelper;
import cn.remex.web.service.BsException;
import cn.remex.web.service.BusinessService;
import cn.remex.web.service.ServiceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;

import java.util.*;

/**
 * Disc:
 * Created by xinxinran on 2017/2/9.
 */
public class RemexBizBeanInitializer implements BeanDefinitionRegistryPostProcessor {
    private static final Logger logger = LoggerFactory.getLogger(RemexBizBeanInitializer.class);

    private static List<String> bsPackages = new ArrayList<>();

    static{
        String defaultPackage = "cn.remex";
        bsPackages.add(defaultPackage);
    }

    public void setBsPackages(List<String> curBsPackages) {
        bsPackages.addAll(curBsPackages);
    }
    /**
     * Modify the application context's internal bean definition registry after its
     * standard initialization. All regular bean definitions will have been loaded,
     * but no beans will have been instantiated yet. This allows for adding further
     * bean definitions before the next post-processing phase kicks in.
     *
     * @param registry the bean definition registry used by the application context
     * @throws BeansException in case of errors
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        logger.info("++++++++ Remex package registry : {} ++++++++", new Date());

        Map<String, Class<?>> bsMap = ServiceFactory.getBsMap();
        bsMap.clear();

        for(String packageName : bsPackages){
            Set<Class<?>> orbs = PackageUtil.getClasses(packageName);
            for (Class<?> c : orbs) {
                if (c.isAnnotationPresent(BusinessService.class) && !c.isInterface()) {
                    String bsName = StringHelper.getClassSimpleName(c);
                    if (bsMap.containsKey(bsName))
                        throw new BsException("扫描BusinessPackage发现异常,有重复的bsName:" + bsName);
                    bsMap.put(bsName, c);
                    BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(c.getName());
                    bdb.setScope("singleton");
                    registry.registerBeanDefinition(StringHelper.getClassName(c), bdb.getBeanDefinition());
                }
            }
        }
    }

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for overriding or adding
     * properties even to eager-initializing beans.
     *
     * @param beanFactory the bean factory used by the application context
     * @throws BeansException in case of errors
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}
